#include "stdafx.h"
#include <QEnvPath.h>
#include <qdir.h>
#include <qfile.h>
#include <boost\filesystem.hpp>

QEnvPath	QEnvPath::Invalid;
String		QEnvPath::Separator("/");

QEnvPath::QEnvPath( ) : m_path(){ }
QEnvPath::QEnvPath( const String &path ):m_path(clean(path)){}
QEnvPath::QEnvPath( const QEnvPath& rk ):m_path(clean(rk.m_path)){ }
	
const String& QEnvPath::path() const{ return m_path; }

size_t QEnvPath::size() const{ return m_path.size(); }
bool QEnvPath::empty() const{ return m_path.empty(); }
bool QEnvPath::exists() const{ return isFile() || isDir(); }
bool QEnvPath::isDir() const{ return QDir(TOQT(m_path)).exists(); }
bool QEnvPath::isFile() const{ return QFile(TOQT(m_path)).exists(); }

String& QEnvPath::operator->( ){return m_path; }
String& QEnvPath::operator*( ){return m_path; }
QEnvPath QEnvPath::operator+( const QEnvPath& p ) const { return QEnvPath( m_path + p.m_path ); }
QEnvPath QEnvPath::operator+( const char * p ) const { return QEnvPath( m_path + String(p)); }
QEnvPath QEnvPath::operator+( const String& p ) const { return QEnvPath( m_path + p ); }
QEnvPath QEnvPath::operator+( const std::string& p ) const { return QEnvPath( m_path + p ); }
	
QEnvPath& QEnvPath::operator+=( const QEnvPath& p ) { m_path += p.m_path; return *this; }
QEnvPath& QEnvPath::operator+=( const char* p ) { m_path += String(p); return *this; }
QEnvPath& QEnvPath::operator+=( const String& p ) { m_path += p; return *this; }
QEnvPath& QEnvPath::operator+=( const std::string& p ) { m_path += p; return *this; }
	
QEnvPath QEnvPath::parentDir() const{ 
	size_t p = m_path.data().rfind( '/' );
	if( p == std::string::npos ) p = m_path.data().rfind('\\');
	if( p == std::string::npos ) return "";
	return m_path.substr( 0, p );
}
String QEnvPath::makeRelative( const QEnvPath &parent ) const
{
	String ret = m_path+String(extension().empty()?"/":"");
	String par = parent.m_path.data() + String(parent.extension().empty()?"/":"").data();
	size_t projPos = ret.data().find(par.data());
	if( projPos != std::string::npos ) ret = ret.substr( projPos+par.size(), ret.size()-(projPos+par.size()) );
	return ret;
}
String QEnvPath::dirName( ) const
{
	size_t p=m_path.data().rfind( '/' );
	if( p == String::npos ){
		p = m_path.data().rfind('\\');
		if( p == std::string::npos ) return m_path;
	}
	return clean(m_path.substr( 0, p ));
}
String QEnvPath::fileName( bool with_ext ) const
{
	size_t p=m_path.data().find_last_of( '/' );
	if( p == std::string::npos ){
		p = m_path.data().find_last_of( '\\' );
		if( p == std::string::npos ) return m_path;
	}
	String ret(clean(m_path.substr(p+1, (m_path.size()-(p+1)))));
	if( !with_ext )
	{
		size_t end = ret.data().find_last_of('.');
		if( end != std::string::npos ) ret = ret.substr( 0, end );
	}
	return ret;
}
QEnvPath QEnvPath::rootDir() const
{
	if( m_path.empty() || m_path.size() == 1 ) return *this;

	// offset of 1 when searching if folder name of format /dir/blah
	size_t p = m_path.data().find_first_of('/',1);
	if( p == std::string::npos ) return *this;
	QEnvPath path( m_path.substr( 0, p ) );
	if( path.empty() )
		return "/";
	return path;
}

String QEnvPath::extension() const
{
	size_t p = fileName(true).data().rfind( '.' );
	if( p != String::npos ) return m_path.substr( p+1, m_path.size()-(p+1) );
	return "";
}
QEnvPath::operator String() const{ return m_path; }
QEnvPath::operator std::string() const{ return m_path; }
QEnvPath::operator bool() const{ return exists(); }
QEnvPath::operator QString() const{ return m_path; }

bool QEnvPath::operator == ( const QEnvPath& rk ) const{ return m_path == rk.m_path; }
bool QEnvPath::operator != ( const QEnvPath& rk ) const{ return m_path != rk.m_path; }

void QEnvPath::clean( )
{
	m_path=clean( m_path );
}
QEnvPath& QEnvPath::operator = ( const String &path ){
	m_path = clean(path);
	return *this;
}
QEnvPath& QEnvPath::operator = ( const QEnvPath& rk ){
	m_path = clean(rk);
	return *this;
}
QEnvPath& QEnvPath::operator = ( const std::string &path ){
	m_path = clean(path);
	return *this;
}
QEnvPath& QEnvPath::operator = ( const char *path ){
	m_path = clean(path);
	return *this;
}
String QEnvPath::clean( String str ) const
{
	str = str.trimmed();
	str.replace( "\\", "/" );
	str.replace( "//", "/" );
	while( !str.empty() && str.at(0) == '/') str.remove(0,1);
	while( !str.empty() && str.at(str.size()-1) == '/') str.remove(str.size()-1,1);
	if( !str.empty() ) str = str.trimmed();
	return str;
}
std::ostream& operator << ( std::ostream& strm, const QEnvPath& path )
{
	strm << path.path();
	return strm;
}
